using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ThridGroup.ERP.DTO;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.ObjectMapping;
using Microsoft.Extensions.Logging;

namespace ThridGroup.ERP.ProductionSystem
{
    /// <summary>
    /// 物料产品分类服务实现
    /// </summary>
    public class MaterialTypeService : ApplicationService, IMaterialTypeService
    {
        private readonly IRepository<MaterialType, int> _materialTypeRepository;
        private readonly ILogger<MaterialTypeService> _logger;

        public MaterialTypeService(
            IRepository<MaterialType, int> materialTypeRepository,
            ILogger<MaterialTypeService> logger)
        {
            _materialTypeRepository = materialTypeRepository;
            _logger = logger;
        }

        /// <summary>
        /// 添加物料分类
        /// </summary>
        public async Task<int> AddMaterialType(MaterialTypeDto materialTypeDto)
        {
            try
            {
                _logger.LogInformation($"开始添加物料分类：{System.Text.Json.JsonSerializer.Serialize(materialTypeDto)}");

                if (materialTypeDto == null)
                {
                    throw new ArgumentNullException(nameof(materialTypeDto));
                }

                if (string.IsNullOrWhiteSpace(materialTypeDto.MaterialTypeName))
                {
                    throw new ArgumentException("分类名称不能为空");
                }

                var entity = ObjectMapper.Map<MaterialTypeDto, MaterialType>(materialTypeDto);
                entity.CreateTime = DateTime.Now;
                entity.IsDeleted = false;

                var result = await _materialTypeRepository.InsertAsync(entity);
                _logger.LogInformation($"成功添加物料分类，ID：{result.Id}");

                return result.Id;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"添加物料分类失败：{System.Text.Json.JsonSerializer.Serialize(materialTypeDto)}");
                throw;
            }
        }

        /// <summary>
        /// 获取所有物料分类
        /// </summary>
        public async Task<List<MaterialTypeDto>> GetMaterialTypes()
        {
            try
            {
                _logger.LogInformation("开始获取物料分类列表");

                // 获取所有未删除的记录并按ParentId和排序号排序
                var list = await _materialTypeRepository.GetListAsync(x => !x.IsDeleted);
                var orderedList = list.OrderBy(x => x.ParentId).ThenBy(x => x.Index).ToList();
                
                _logger.LogInformation($"从数据库获取到{orderedList.Count}条记录");

                // 转换为DTO
                var dtoList = ObjectMapper.Map<List<MaterialType>, List<MaterialTypeDto>>(orderedList);
                
                // 为每个项目设置额外的属性
                foreach (var dto in dtoList)
                {
                    // 设置父级名称
                    if (dto.ParentId > 0)
                    {
                        var parent = orderedList.FirstOrDefault(x => x.Id == dto.ParentId);
                        if (parent != null)
                        {
                            dto.ParentName = parent.MaterialTypeName;
                        }
                    }
                }

                _logger.LogInformation($"成功处理{dtoList.Count}条记录");
                return dtoList;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取物料分类列表失败");
                throw;
            }
        }

        /// <summary>
        /// 获取单个物料分类
        /// </summary>
        public async Task<MaterialTypeDto> GetMaterialType(int id)
        {
            try
            {
                _logger.LogInformation($"开始获取物料分类，ID：{id}");

                if (id <= 0)
                {
                    throw new ArgumentException("无效的ID");
                }

                var entity = await _materialTypeRepository.GetAsync(id);
                if (entity == null)
                {
                    throw new Exception($"未找到ID为{id}的物料分类");
                }

                var dto = ObjectMapper.Map<MaterialType, MaterialTypeDto>(entity);
                _logger.LogInformation($"成功获取物料分类，ID：{id}");

                return dto;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取物料分类失败，ID：{id}");
                throw;
            }
        }

        /// <summary>
        /// 更新物料分类
        /// </summary>
        public async Task<int> UpdateMaterialType(MaterialTypeDto materialTypeDto)
        {
            try
            {
                _logger.LogInformation($"开始更新物料分类：{System.Text.Json.JsonSerializer.Serialize(materialTypeDto)}");

                if (materialTypeDto == null)
                {
                    throw new ArgumentNullException(nameof(materialTypeDto));
                }

                if (materialTypeDto.Id <= 0)
                {
                    throw new ArgumentException("无效的ID");
                }

                if (string.IsNullOrWhiteSpace(materialTypeDto.MaterialTypeName))
                {
                    throw new ArgumentException("分类名称不能为空");
                }

                var entity = await _materialTypeRepository.GetAsync(materialTypeDto.Id);
                if (entity == null)
                {
                    throw new Exception("物料分类不存在");
                }

                // 更新实体属性
                entity.MaterialTypeName = materialTypeDto.MaterialTypeName;
                entity.ParentId = materialTypeDto.ParentId;
                entity.Index = materialTypeDto.Index;
                entity.IsEnable = materialTypeDto.IsEnable;

                var result = await _materialTypeRepository.UpdateAsync(entity);
                _logger.LogInformation($"成功更新物料分类，ID：{result.Id}");

                return result.Id;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"更新物料分类失败：{System.Text.Json.JsonSerializer.Serialize(materialTypeDto)}");
                throw;
            }
        }

        /// <summary>
        /// 删除物料分类
        /// </summary>
        public async Task DeleteMaterialType(int id)
        {
            try
            {
                _logger.LogInformation($"开始删除物料分类，ID：{id}");

                if (id <= 0)
                {
                    throw new ArgumentException("无效的ID");
                }

                // 检查是否有子分类
                var children = await _materialTypeRepository.GetListAsync(x => x.ParentId == id && !x.IsDeleted);
                if (children.Any())
                {
                    throw new Exception("该分类下存在子分类，无法删除");
                }

                var entity = await _materialTypeRepository.GetAsync(id);
                if (entity == null)
                {
                    throw new Exception($"未找到ID为{id}的物料分类");
                }

                entity.IsDeleted = true;
                await _materialTypeRepository.UpdateAsync(entity);
                _logger.LogInformation($"成功删除物料分类，ID：{id}");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"删除物料分类失败，ID：{id}");
                throw;
            }
        }

        /// <summary>
        /// 获取物料分类树形结构
        /// </summary>
        public async Task<List<MaterialTypeDto>> GetMaterialTypeTree()
        {
            try
            {
                _logger.LogInformation("开始获取物料分类树形结构");

                var allTypes = await _materialTypeRepository.GetListAsync(x => !x.IsDeleted);
                var orderedTypes = allTypes.OrderBy(x => x.Index).ToList();
                
                // 获取根节点
                var rootTypes = orderedTypes.Where(x => x.ParentId == 0).ToList();
                var result = ObjectMapper.Map<List<MaterialType>, List<MaterialTypeDto>>(rootTypes);

                // 递归构建树结构
                foreach (var root in result)
                {
                    await BuildMaterialTypeTree(orderedTypes, root);
                }

                _logger.LogInformation($"成功获取物料分类树形结构，共{result.Count}个根节点");
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取物料分类树形结构失败");
                throw;
            }
        }

        private async Task BuildMaterialTypeTree(List<MaterialType> allTypes, MaterialTypeDto parent)
        {
            var children = allTypes
                .Where(x => x.ParentId == parent.Id)
                .OrderBy(x => x.Index)
                .ToList();

            if (children.Any())
            {
                parent.Children = ObjectMapper.Map<List<MaterialType>, List<MaterialTypeDto>>(children);
                foreach (var child in parent.Children)
                {
                    await BuildMaterialTypeTree(allTypes, child);
                }
            }
        }
    }
} 